local _G = GLOBAL
if _G.TheNet:IsDedicated() or _G.TheNet:GetServerGameMode() == "lavaarena" then return end
if GetModConfigData("WORMHOLE_MARKS_DISABLE") then
    if _G.KnownModIndex:IsModEnabled("workshop") or _G.KnownModIndex:IsModTempEnabled("workshop") then return end
end

local require = _G.require
local unpack = _G.unpack
local FindEntity = _G.FindEntity
local Vector3 = _G.Vector3

local PersistentData = require("persistentdata")
local PersistentMapIcons = require("widgets/persistentmapicons")
local DataContainer = PersistentData("mod_wormholeicons")

local SHOW_NUMBERS = GetModConfigData("SHOW_NUMBERS")
local ICON_STYLE = GetModConfigData("ICON_STYLE")
local wormhole_path = "images/wormhole_"..SHOW_NUMBERS..ICON_STYLE
local tentapillar_path = "images/tentapillar_"..SHOW_NUMBERS..ICON_STYLE

Assets = {
    Asset("IMAGE", wormhole_path..".tex"),
    Asset("ATLAS", wormhole_path..".xml"),
    Asset("IMAGE", tentapillar_path..".tex"),
    Asset("ATLAS", tentapillar_path..".xml"),
}

AddMinimapAtlas(wormhole_path..".xml")
AddMinimapAtlas(tentapillar_path..".xml")

PrefabFiles = {
    "border_circle",
}

local WormholePositions = {}
local world_key
local function SaveWormholePositions()
    local s_list = {}
    for i, pos in ipairs(WormholePositions) do
        s_list[i] = {x = pos.x, y = pos.y, z = pos.z}
    end
    DataContainer:SetValue(world_key, s_list)
    DataContainer:Save()
end

local function LoadWormholePositions()
    DataContainer:Load()
    local s_list = DataContainer:GetValue(world_key)
    if s_list then
        for i, pos in ipairs(s_list) do
            WormholePositions[i] = Vector3(pos.x, pos.y, pos.z)
            print("[Wormhole Icons] Loaded icon at "..tostring(WormholePositions[i]))
        end
    end
end

local function WormholePositionExists(new_pos)
    for i, pos in ipairs(WormholePositions) do
        if pos:__eq(new_pos) then return i end
    end
    return false
end

local function AddWormholePosition(pos)
    table.insert(WormholePositions, pos)
    print("[Wormhole Icons] Added icon at "..tostring(pos))
end

local texture, xml_path
AddSimPostInit(function()
    local TheWorld = _G.TheWorld
    local cave = TheWorld:HasTag("cave")
    world_key = (cave and "cave_" or "world_")..TheWorld.meta.seed
    texture = cave and "tentapillar_" or "wormhole_"
    xml_path = cave and tentapillar_path or wormhole_path
    LoadWormholePositions()
    print("[Wormhole Icons] World Key: "..world_key)
end)

local scale = {new = 0.85, old = 0.75}
AddClassPostConstruct("widgets/mapwidget", function(self)
    self.wormholeicons = self:AddChild(PersistentMapIcons(self, scale[ICON_STYLE]))
    for i, pos in ipairs(WormholePositions) do
        local key = math.ceil(i / 2)
        self.wormholeicons:AddMapIcon(xml_path..".xml", texture..key..".tex", pos)
    end
end)

local function RGB(r, g, b)
    return {r / 255, g / 255, b / 255, 1}
end

local colors = {
    RGB(255, 0, 32),    -- red
    RGB(0, 225, 255),   -- teal
    RGB(96, 64, 255),   -- purple
    RGB(0, 255, 75),    -- green
    RGB(255, 75, 0),    -- orange
    RGB(0, 128, 255),   -- blue
    RGB(96, 200, 32),   -- lime
    RGB(255, 32, 128),  -- pink
    RGB(182, 255, 0),   -- yellow
    RGB(64, 64, 64),    -- gray
}

local WORLD_COLORS = GetModConfigData("WORLD_COLORS")
local WORLD_NUMBERS = GetModConfigData("WORLD_NUMBERS")
local WORMHOLE_BORDER = GetModConfigData("WORMHOLE_BORDER")
local MINIMAP_ICONS = GetModConfigData("MINIMAP_ICONS")
local function AddWormholeColor(inst, pos)
    if not inst or not inst:IsValid() or not pos or inst.color_done then return end
    local i = WormholePositionExists(pos)
    if not i then return end
    local key = math.ceil(i / 2)
    if WORLD_COLORS then
        local add_color = 0.15
        inst.AnimState:SetAddColour(add_color, add_color, add_color, 0)
        inst.AnimState:OverrideMultColour(unpack(colors[key]))
    end
    if WORLD_NUMBERS then
        local label = inst.entity:AddLabel()
        label:SetFont(_G.CHATFONT_OUTLINE)
        label:SetFontSize(35)
        label:SetWorldOffset(0, 2, 0)
        local num = key == 10 and 0 or key
        label:SetText(" "..num.." ")
        label:SetColour(unpack(colors[key]))
        label:Enable(true)
    end
    if WORMHOLE_BORDER then
        if inst.prefab == "wormhole" then
            inst.AnimState:SetLayer(_G.LAYER_WORLD_BACKGROUND)
        end
        inst.border_circle = inst:SpawnChild("border_circle")
        inst.border_circle.AnimState:SetAddColour(unpack(colors[key]))
    end
    if MINIMAP_ICONS then
        inst.MiniMapEntity:SetIcon(texture..key..".tex")
    end
    inst.color_done = true
end

local wormhole_types = {tentacle_pillar_hole = true, tentacle_pillar = true, wormhole = true}
for prefab in pairs(wormhole_types) do
    AddPrefabPostInit(prefab, function(inst)
        inst:DoTaskInTime(0.2, function() AddWormholeColor(inst, inst:GetPosition()) end)
    end)
end

local function GetWormhole()
    local wormhole = FindEntity(_G.ThePlayer, 5, function(inst) return wormhole_types[inst.prefab] end, {"teleporter"})
    if wormhole then
        return {inst = wormhole, pos = wormhole:GetPosition()}
    end
    return false
end

local function SaveWormholePair(entrance, exit)
    if not entrance.pos:__eq(exit.pos) then
        AddWormholePosition(entrance.pos)
        AddWormholePosition(exit.pos)
        SaveWormholePositions()
        AddWormholeColor(entrance.inst, entrance.pos)
        AddWormholeColor(exit.inst, exit.pos)
    else
        print("[Wormhole Icons] Error saving wormhole pair")
    end
end

AddPrefabPostInit("player_classified", function(player_classified)
    player_classified:ListenForEvent("wormholetraveldirty", function()
        local entrance = GetWormhole()
        if entrance and not WormholePositionExists(entrance.pos) then
            _G.ThePlayer:DoTaskInTime(3, function()
                local exit = GetWormhole()
                if exit and not WormholePositionExists(exit.pos) then
                    SaveWormholePair(entrance, exit)
                end
            end)
        end
    end)
end)

--[[Console Commands]]

function _G.c_removewormholeicon()
    local wormhole = GetWormhole()
    if wormhole then
        local i = WormholePositionExists(wormhole.pos)
        if not i then return end
        WormholePositions[i] = nil
        print("[Wormhole Icons] Removed icon at "..tostring(wormhole.pos))
    end
end

function _G.c_removeallwormholeicons()
    for i in ipairs(WormholePositions) do
        WormholePositions[i] = nil
    end
    print("[Wormhole Icons] All icons removed")
end

function _G.c_savewormholepositions()
    SaveWormholePositions()
    print("[Wormhole Icons] All positions saved to file")
end

function _G.c_setwormholecolor(r, g, b)
    if not r or not g or not b then return end
    local wormhole = GetWormhole()
    if wormhole and wormhole.inst.border_circle then
        local color = RGB(r, g, b)
        wormhole.inst.AnimState:OverrideMultColour(unpack(color))
        wormhole.inst.border_circle.AnimState:SetAddColour(unpack(color))
        print("[Wormhole Icons] Red: "..r.." Green: "..g.." Blue: "..b)
    end
end